﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

/// <summary>
/// ECS系统基类
/// </summary>
    public class ECSSystemtBase
{
    public ECSWorldBase MyWorld;

    #region Filter(virtual)
    private string[] m_filter;

    private int m_filterNum;
    /// <summary>
    /// 过滤组件类型名
    /// </summary>
    public string[] Filter
    {
        get
        {
            if (m_filter == null)
            {
                Type[] types = GetFilter();
                m_filterNum = types.Length;
                m_filter = new string[m_filterNum];
                for (int i = 0; i < m_filterNum; i++)
                {
                    m_filter[i] = types[i].Name;
                }
            }

            return m_filter;
        }
        set { }
    }
    /// <summary>
    /// 获取该系统的过滤组件类型
    /// </summary>
    /// <returns></returns>
    public virtual Type[] GetFilter()
    {
        return new Type[0];
    }


    #endregion

    #region 系统名Name
    private string m_name;
    /// <summary>
    /// 系统名
    /// </summary>
    public string Name
    {
        get
        {
            if (string.IsNullOrEmpty(m_name))
            {
                m_name = this.GetType().Name;
            }

            return m_name;
        }
        set { m_name = value; }
    }


    #endregion

    #region OnInit/OnDispose/OnGameStart/RunByPause(virtual)

    public virtual void OnInit()
    {

    }

    public virtual void OnDispose()
    {

    }

    public virtual void OnGameStar()
    {

    }

    public virtual void RunByPause()
    {

    }
    /// <summary>
    /// 重计算，只在sync系统使用
    /// </summary>
    public virtual void Recalc() { }
    #endregion

    #region Update/BeforeUpdate/LateUpdate(virtual)显示
    public virtual void BeforeUpdate(int deltaTime) { }
   
    public virtual void Update(int deltaTime) { }
 
    public virtual void LateUpdate(int deltaTime) { }
    
    #endregion

    #region BeforeFixedUpdate/FixedUpdate/LateFixedUpdate(virtual)逻辑
    public virtual void BeforeFixedUpdate(int delaTime) { }
    public virtual void FixedUpdate(int delaTime) { }
    public virtual void LateFixedUpdate(int delaTime) { }

    #endregion

    #region EndFrame(virtual)
    public virtual void EndFrame(int deltaTime) { }


    #endregion

    #region GetAllExistComp(string[],entity)询问该实体是否包含此过滤器（组件类型type.name）
    /// <summary>
    /// 询问该实体是否包含此过滤器（组件类型type.name）
    /// </summary>
    /// <param name="compNames"></param>
    /// <param name="entity"></param>
    /// <returns></returns>
    public bool GetAllExistComp(string[] compNames, ECSEntityBase entity)
    {
        for (int i = 0,j=compNames.Length; i < j; i++)
        {
            if (!entity.GetExistCom(compNames[i]))
            {
                return false;
            }
        }

        return true;
    }



    #endregion

    #region 从世界ecs组管理器中寻找符合过滤器的一组实体 GetEntityList
    /// <summary>
    /// 是否已获取该系统的过滤器哈希，不需重复计算
    /// </summary>
    private bool isGetHashCode = false;
    /// <summary>
    /// 该系统的组件类型名所得到的过滤哈希
    /// </summary>
    private int filterNameHashCode;
    /// <summary>
    /// 从世界ecs组管理器中寻找符合过滤器的一组实体
    /// </summary>
    /// <returns></returns>
    public List<ECSEntityBase> GetEntityList()
    {
        if (!isGetHashCode)
        {
            isGetHashCode = true;
            //组管理器中把一组组件类型名转换为int
            filterNameHashCode = GetGroupHashCode(Filter);
        }
        //组管理器中通过过滤哈希和过滤数组获取符合的一组 实体
        return GetGroupEntityList(filterNameHashCode, Filter);
    }

    public List<ECSEntityBase> GetEntityList(string[] filter)
    {
        ////组管理器中把一组组件类型名转换为int
        int hashCode = GetGroupHashCode(filter);
        //组管理器中通过过滤哈希和过滤数组获取符合的一组 实体
        return GetGroupEntityList(filterNameHashCode, Filter);
    }

    #endregion

    #region 从世界的ECS组管理器中匹配过滤器对应的哈希，哈希对应的实体列表GetGroupHashCode/GetGroupEntityList
    /// <summary>
    /// 从组管理器中获取对应过滤器的哈希
    /// </summary>
    /// <param name="filter"></param>
    /// <returns></returns>
    public int GetGroupHashCode(string[] filter)
    {
        return MyWorld.group.StringArrayToInt(filter);
    }
    /// <summary>
    /// 从组管理器中获取对应过滤的一组实体
    /// </summary>
    /// <param name="hash"></param>
    /// <param name="filter"></param>
    /// <returns></returns>
    public List<ECSEntityBase> GetGroupEntityList(int hash, string[] filter)
    {
        return MyWorld.group.GetEntityByFilter(hash, filter);
    }


    #endregion

    #region 事件监听（向世界实体改变监听中<注入>/<移除>系统的监听BBB）

    #region 添加监听

    protected void AddEntityCreateListener()
    {
        MyWorld.OnEntityCreate += OnEntityCreate;

    }
    protected void AddEntityOptimizeCreateListener()
    {
        MyWorld.OnEntityOptimizeCreate+= OnEntityOptimizeCreate;

    }
    protected void AddEntityDestoryListener()
    {
        MyWorld.OnEntityDestory += OnEntityDestory;

    }
    protected void AddEntityOptimizeDestoryListener()
    {
        MyWorld.OnEntityOptimizeDestory += OnEntityOptimizeDestroy;

    }
    protected void AddEntityWillBeDestoryListener()
    {
        MyWorld.OnEntityWillBeDestory += OnEntityWillBeDestory;

    }
    protected void AddEntityOptimizeWillBeDestoryListener()
    {
        MyWorld.OnEntityOptimizeWillBeDestory += OnEntityOptimizeWillBeDestroy;

    }
    protected void AddEntityComAddListener()
    {
        MyWorld.OnEntityCoompAdd += OnEntityCompAdd;
    }
    protected void AddEntityComRemoveListener()
    {
        MyWorld.OnEntityCoompRemove += OnEntityCompRemove;
    }
    protected void AddEntityComChangeListener()
    {
        MyWorld.OnEntityCoompChange += OnEntityCompChange;
    }

    #endregion
    #region 移除监听

    protected void RemoveEntityCreateListener()
    {
        MyWorld.OnEntityCreate -= OnEntityCreate;

    }
    protected void RemoveEntityOptimizeCreateListener()
    {
        MyWorld.OnEntityOptimizeCreate -= OnEntityOptimizeCreate;

    }
    protected void RemoveEntityDestoryListener()
    {
        MyWorld.OnEntityDestory -= OnEntityDestory;

    }
    protected void RemoveEntityOptimizeDestoryListener()
    {
        MyWorld.OnEntityOptimizeDestory -= OnEntityOptimizeDestroy;

    }
    protected void RemoveEntityWillBeDestoryListener()
    {
        MyWorld.OnEntityWillBeDestory -= OnEntityWillBeDestory;

    }
    protected void RemoveEntityOptimizeWillBeDestoryListener()
    {
        MyWorld.OnEntityOptimizeWillBeDestory -= OnEntityOptimizeWillBeDestroy;

    }
    private void RemoveEntityComAddListener()
    {
        MyWorld.OnEntityCoompAdd -= OnEntityCompAdd;
    }
    private void RemoveEntityComRemoveListener()
    {
        MyWorld.OnEntityCoompRemove -= OnEntityCompRemove;
    }
    private void RemoveEntityComChangeListener()
    {
        MyWorld.OnEntityCoompChange -= OnEntityCompChange;
    }

    #endregion
    #endregion

    #region 事件回调（BBB）virtual 实体创建销毁回调，实体组件更改回调
    public virtual void OnEntityCreate(ECSEntityBase entity) { }
    public virtual void OnEntityOptimizeCreate(ECSEntityBase entity)
    {

    }
    public virtual void OnEntityDestory(ECSEntityBase entity) { }
    public virtual void OnEntityOptimizeDestroy(ECSEntityBase entity)
    {

    }
    public virtual void OnEntityWillBeDestory(ECSEntityBase entity) { }
    public virtual void OnEntityOptimizeWillBeDestroy(ECSEntityBase entity)
    {

    }
    public virtual void OnEntityCompAdd(ECSEntityBase entity,int compIndex,ECSCompoentBase com) { }
    public virtual void OnEntityCompRemove(ECSEntityBase entity, int compIndex, ECSCompoentBase com) { }
    public virtual void OnEntityCompChange(ECSEntityBase entity, int compIndex, ECSCompoentBase com,ECSCompoentBase newCom) { }
    #endregion

    #region 组件类型名转索引

    public int ToIndex(string comName)
    {
        return MyWorld.compoentType.GetCompoentIndex(comName);
    }


    #endregion
}

